package storage

import (
	"context"
	"io"
	"mime/multipart"

	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

type _FileDao struct {
	bucket *mongo.GridFSBucket
}

func newFileDao(db *mongo.Database) (*_FileDao, error) {
	bucket := db.GridFSBucket()
	return &_FileDao{bucket: bucket}, nil
}

func (dao *_FileDao) Save(ctx context.Context, file *multipart.FileHeader) (string, string, error) {
	fileReader, err := file.Open()
	if err != nil {
		return "", "", err
	}
	defer fileReader.Close()
	fileId := uuid.NewString()
	fileToken := uuid.NewString()
	contentType := file.Header.Get("Content-Type")
	err = dao.bucket.UploadFromStreamWithID(ctx, fileId, file.Filename, fileReader,
		options.GridFSUpload().SetMetadata(bson.M{"fileToken": fileToken, "contentType": contentType}))
	return fileId, fileToken, err
}

func (dao *_FileDao) Get(ctx context.Context, fileId string) (io.ReadCloser, string, string, error) {
	stream, err := dao.bucket.OpenDownloadStream(ctx, fileId)
	if err != nil {
		return nil, "", "", err
	}
	meta := stream.GetFile().Metadata
	fileTokenVal := meta.Lookup("fileToken")
	fileToken, _ := fileTokenVal.StringValueOK()
	contentTypeVal := meta.Lookup("contentType")
	contentType, _ := contentTypeVal.StringValueOK()
	return stream, fileToken, contentType, nil
}
